package com.chenyun.system.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.lang.UUID;
import com.chenyun.common.constants.AuthConstant;
import com.chenyun.common.context.SpringContext;
import com.chenyun.common.exceptions.BusinessException;
import com.chenyun.common.exceptions.CommonException;
import com.chenyun.common.utils.IpUtils;
import com.chenyun.common.vo.AjaxResult;
import com.chenyun.system.param.SendSmsParam;
import com.chenyun.system.service.impl.CommonServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Lonni
 * @date 2022-06-15 18:25
 */
@RestController
@RequestMapping("/comm")
@Api(tags = "工具")
@Slf4j
public class CommonController {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CommonServiceImpl commonService;


    @ApiOperation(value = "发送手机验证码,2分钟过期")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true),
            @ApiImplicitParam(name = "type", value = "业务类型", required = true),

    })
    @GetMapping("/getVerifCode")
    @SneakyThrows
    public AjaxResult sengPhoneCode(String phone, Integer type, HttpServletResponse response) throws IOException {
        commonService.sengPhoneCode(new ArrayList<SendSmsParam>() {{
            add(SendSmsParam.builder()
                    .phone(phone)
                    .type(type).build());
        }});
        return AjaxResult.SUCCESS("验证码已发送!");

    }


    private CircleCaptcha createImgCode(HttpServletRequest request, HttpServletResponse response, String uuid) throws IOException {
        String codeKey = AuthConstant.AUTH_CATCHA_CACHE_KEY + uuid;
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
        String code = captcha.getCode();
        log.debug("生成算术类验证码完成,结果:{}", code);
        log.debug("生成算术类验证码完成,获取uuid地址结果:{}", uuid);
        if (SpringContext.isTest()) {
            redisTemplate.opsForValue().set(codeKey, captcha.getCode(), 2, TimeUnit.HOURS);
        } else {
            redisTemplate.opsForValue().set(codeKey, captcha.getCode(), 2, TimeUnit.MINUTES);
        }
        return captcha;

    }

    @ApiOperation(value = "获取图片验证码,2分钟过期,且4分钟只能刷新20次;返回base64")
    @GetMapping("/getImgCode")
    public AjaxResult getImgCode(HttpServletRequest request, HttpServletResponse response) throws IOException, CommonException {
        String ipAddr = IpUtils.getIpAddr(request);
        String uuid = UUID.fastUUID().toString();
        String refreshKey = AuthConstant.AUTH_CATCHA_COUNT_CACHE_KEY + ipAddr;
        Object refreshCount = redisTemplate.opsForValue().get(refreshKey);
        if (refreshCount != null) {
            Integer count = (Integer) refreshCount;
            if (count > 20) {
                //4分钟只能刷新20次
                throw new BusinessException("请不要频繁刷新");
            }
        }
        CircleCaptcha imgCode = createImgCode(request, response, uuid);
        log.info("图片验证码生成成功:{}", imgCode.getCode());
        //设置防刷 4分钟只能刷新20次
        redisTemplate.opsForValue().increment(refreshKey, 1);
        if (refreshCount == null) {
            redisTemplate.expire(refreshKey, 4, TimeUnit.MINUTES);
        }
        Map data = new HashMap<String, String>() {{
            put("img", imgCode.getImageBase64());
            put("uuid", uuid);
        }};
        return AjaxResult.SUCCESS(data);
    }


}
